package com.zbmy.plugin.im.server.core.back.server.hanler;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

import java.util.concurrent.BlockingQueue;

import org.apache.log4j.Logger;

import com.zbmy.plugin.im.server.core.model.ChannelInfo;
import com.zbmy.plugin.im.server.core.protocol.MessageHolder;
import com.zbmy.plugin.im.server.core.protocol.ProtocolHeader;
import com.zbmy.plugin.im.server.core.queue.TaskQueue;
import com.zbmy.plugin.im.server.core.session.UserSessionManger;

/**
 * 
 * 核心处理器
 * @ClassName: IoHandler    
 * @author 杨乐平    
 * @date 2018年4月28日 下午5:07:23    
 * @version  v 1.0
 */
public class BackIoHandler extends ChannelInboundHandlerAdapter  {
	private Logger logger = Logger.getLogger(BackIoHandler.class);
	// 丢失的心跳数
    private volatile int counter = 0;
	// 消息中转queue
	private final BlockingQueue<MessageHolder> taskQueue;
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		UserSessionManger.channelGroup.add(ctx.channel());
		ChannelInfo channelInfo = new ChannelInfo(ctx);
		UserSessionManger.addChannelInfo(ctx.channel(), channelInfo);
	}

    public BackIoHandler() {
        taskQueue = TaskQueue.getQueue();
    }

     @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof MessageHolder) {
            MessageHolder messageHolder = (MessageHolder) msg;
            String body = messageHolder.getBody();
            System.out.println("内容长度 =  " + body.length());
            
            // 可以做转发，先判断当前用户是否存在
            
            // 指定Channel
            messageHolder.setChannel(ctx.channel());
            if (messageHolder.getType() == ProtocolHeader.TYPE_HEARTBEAT) {  // 消息类型为心跳
               /* if (username == null) {
                    username = ConnPool.query(channel);
                }*/
                counter = 0;// 心跳丢失清零
                //logger.info(username + " 收到心跳包");
                //ReferenceCountUtil.release(msg);
            }else{
            	// 添加到任务队列
                boolean offer = taskQueue.offer(messageHolder);
                //logger.info("TaskQueue添加任务: taskQueue=" + taskQueue.size());
                if (!offer) {
                    // 服务器繁忙
                    //logger.warn("服务器繁忙，拒绝服务");
                    // 繁忙响应
                    MessageHolder responseMessageHolder = new MessageHolder();
                    responseMessageHolder.setSign(ProtocolHeader.SIGN_RESPONSE);
                    responseMessageHolder.setType(messageHolder.getSign());
                    //responseMessageHolder.setStatus(ProtocolHeader.SERVER_BUSY);
                    responseMessageHolder.setBody("");
                    ctx.channel().writeAndFlush(responseMessageHolder);
                }
            }
        } else {
            throw new IllegalArgumentException("msg is not instance of MessageHolder");
        }
    }
    
    /*@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    	//ByteBuf body = (ByteBuf)msg;
    	System.out.println("我槽");
    }*/

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		//logger.error("业务逻辑出错", cause);
		/*if (username == null) {
            username = ConnPool.query(channel);
        }*/
        // 心跳丢失
        counter++;
        //logger.info(username + " 丢失" + counter + "个心跳包");
        if (counter >= 5) {
            // 心跳丢失数达到5个，主动断开连接
        	Channel channel = ctx.channel();
        	UserSessionManger.channelGroup.remove(channel);
        	UserSessionManger.removeChannelInfo(channel);
        	channel.close();
        	//cause.printStackTrace();
            logger.error("失去连接");
    		ctx.close();
        }
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
			throws Exception {
		//心跳包检测读超时
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent e = (IdleStateEvent) evt;
			if (e.state() == IdleState.ALL_IDLE) {
				//logger.info("客户端读超时");
				Channel channel = ctx.channel();
				//SpringContext.getUserService().userLogout(channel, SessionCloseReason.OVER_TIME);
			}
		}
	}
	
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();		// 完成读取，那么flush一下
	}
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
	}
}
